package com.pdf.pdfserver.service;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.pdf.parser.*;
import com.pdf.pdfserver.config.PdfContext;
import com.pdf.pdfserver.enums.FileSuffixEnum;
import com.pdf.pdfserver.enums.WaterMarkEnum;
import com.pdf.pdfserver.service.read.image.pdf.ImageRenderListener;
import com.pdf.pdfserver.service.read.text.IfReadService;
import com.pdf.pdfserver.service.read.text.factory.FileProcessFactory;
import com.pdf.pdfserver.service.solr.ArticleSolrService;
import com.pdf.pdfserver.service.write.PdfCreateService;
import com.pdf.pdfserver.util.PdfFrontCoverUtil;
import com.pdf.pdfserver.util.PdfWaterMarkUtil;
import com.pdf.pdfserver.util.StringUtil;
import com.pdf.pdfserver.vo.ArticleVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

/**
 * @Author songfz
 * @Description pdf处理业务
 * @Date 2022/1/4
 */
@Service
public class PdfService {

    private static Logger LOG = LoggerFactory.getLogger(PdfService.class);

    //生成临时文件前缀
    private static final String prefix = "tempFile";

    @Autowired
    private FileProcessFactory fileProcessFactory;

    @Autowired
    private PdfCreateService pdfCreateService;


    @Autowired
    private ArticleSolrService articleSolrService;

    @Autowired
    private PdfContext pdfContext;

    /**
     * 文件读取及生成PDF文件
     *
     * @param map
     * @param toPath
     */
    public void toPdf(Map<FileSuffixEnum, List<File>> map, String toPath) {

        List<ArticleVO> articleVOS = new ArrayList<>();

        Integer i = 0;
        for (Map.Entry<FileSuffixEnum, List<File>> enumListEntry : map.entrySet()) {

            FileSuffixEnum key = enumListEntry.getKey();
            List<File> value = enumListEntry.getValue();

            for (File file : value) {

                try {

                    String context = readTxt(key, file);
                    LOG.info("读取文件【{}】内容【{}】", file.getName(), context);
                    if (StringUtil.isEmpty(context)) {
                        continue;
                    }

                    ArticleVO articleVO = new ArticleVO();
                    articleVO.setId(String.valueOf(++i));
                    articleVO.setContent(context);
                    articleVOS.add(articleVO);
                    File pathFile = new File(toPath);
                    if (!pathFile.exists()) {
                        pathFile.createNewFile();
                    }
                    // 生成临时文件
                    File newFile = File.createTempFile(toPath + file.getName().substring(0, file.getName().lastIndexOf(".")) + "_" + prefix, ".pdf");

                    // 生成PDF文档并加水印
//                    if (pdfCreateService.create(newFile,context)) {
                    if (pdfCreateService.create(file, newFile)) {
                        String frontCoverPath = toPath + file.getName().substring(0, file.getName().lastIndexOf(".")) + ".jpg";
                        String name = toPath + file.getName().substring(0, file.getName().lastIndexOf(".")) + ".pdf";
                        PdfWaterMarkUtil.addWaterMark(newFile.getPath(), name, pdfContext.getOwnerPassword(), pdfContext.getMarkText(), pdfContext.getMarkImage(),
                                WaterMarkEnum.TEXT);
                        PdfFrontCoverUtil.createFrontCover(newFile, frontCoverPath);
                    }
                } catch (IOException e) {
                    LOG.error(e.getMessage(), e);
                }

                CompletableFuture.runAsync(() -> articleVOS.stream().forEach(articleVO -> articleSolrService.addArticle(articleVO)));
            }
        }
    }

    private String readTxt(FileSuffixEnum key, File file) throws FileNotFoundException {
        BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file));
        IfReadService ifReadService = fileProcessFactory.toBean(key);
        if (null == ifReadService) {
            return null;
        }
        return ifReadService.read(key, inputStream);
    }

    public void officeToPDF(Map<FileSuffixEnum, List<File>> map, String toPath) {
        for (Map.Entry<FileSuffixEnum, List<File>> enumListEntry : map.entrySet()) {

            FileSuffixEnum key = enumListEntry.getKey();
            List<File> value = enumListEntry.getValue();

            for (File file : value) {
                String name = toPath + file.getName().substring(0, file.getName().lastIndexOf(".")) + ".pdf";
                // 如果目标路径不存在, 则新建该路径
                File outputFile = new File(name);
                if (!outputFile.getParentFile().exists()) {
                    outputFile.getParentFile().mkdirs();
                }
                pdfCreateService.create(file, outputFile);
            }
        }
    }


    /**
     * PDF文件中加入图片
     *
     * @param inPath    源文件
     * @param outPath   输出文件
     * @param imagePath 图片
     * @param pageIndex 第几页添加图片
     * @return
     */
    public Boolean insertPic(String inPath, String outPath, String imagePath, Integer pageIndex) {

        PdfReader reader = null;
        PdfStamper stamper = null;
        try {
            reader = new PdfReader(new FileInputStream(new File(inPath)));


            stamper = new PdfStamper(reader, new FileOutputStream(new File(outPath)));

            // 提取pdf中的表单
            AcroFields form = stamper.getAcroFields();
            //新增空白页
            if (reader.getNumberOfPages() < pageIndex.intValue()) {
                pageIndex = reader.getNumberOfPages() + 1;
            }
            stamper.insertPage(pageIndex, reader.getPageSizeWithRotation(1));

            form.addSubstitutionFont(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED));

            Image image = Image.getInstance(imagePath);
            PdfContentByte overContent = stamper.getOverContent(pageIndex);
            image.scaleToFit(PageSize.A4.getWidth(), PageSize.A4.getHeight());

            image.setAbsolutePosition(0, 0);

            overContent.addImage(image);

            return true;
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            return false;
        } finally {

            Optional.ofNullable(stamper).ifPresent(stamp -> {
                try {
                    stamp.close();
                } catch (Exception e) {
                    LOG.error(e.getMessage(), e);
                }
            });

            reader.close();
        }


    }


    public Integer totalPage(String inPath) {

        PdfReader reader = null;
        try {
            reader = new PdfReader(new FileInputStream(new File(inPath)));
            return reader.getNumberOfPages();
        } catch (IOException e) {
            LOG.error(e.getMessage(), e);
        } finally {
            Optional.ofNullable(reader).ifPresent(pdfReader -> pdfReader.close());
        }
        return 0;
    }

    /**
     * 读取指定页面图片
     * @param pdfPath
     * @param imagePath 图片输入地址
     * @param pageIndex 页数
     */
    public void readPic(String pdfPath, String imagePath, Integer pageIndex) {

        PdfReader reader = null;
        File file = new File(pdfPath);
        try {
             reader = new PdfReader(new FileInputStream(file));

            PdfReaderContentParser contentParser = new PdfReaderContentParser(reader);

            contentParser.processContent(pageIndex, new ImageRenderListener(imagePath));

        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }finally {
            reader.close();
        }
    }
}
